package com.cy.sys.Aop;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import com.cy.sys.Aop.ancution.requestCache;

@Aspect
@Component
public class syscaheaspect {
	//假设一个cache容器
	Map<String,Object> map = new ConcurrentHashMap<>();//线程安全的map
	
	//切入点方法(细腻度的切入点).用于指定方法的切入点	
	@Pointcut("@annotation(com.cy.sys.Aop.ancution.requestCache)")
	public void docache() {}
	
	@Pointcut("@annotation(com.cy.sys.Aop.ancution.clearCache)")
	public void clearcache() {}
	
	
	@AfterReturning("clearcache()")
	public void doclearcache() throws Throwable {
		//清除cache
		map.clear();
	}
	
	
	@Around("docache()")
	public Object docachetext(ProceedingJoinPoint jp) throws Throwable {
		//1.从cache中获取数据,有则查询返回
		System.out.println("from cache");
		
		//获取注解上的值；问题完成
		//FAQ?如何将cache中的key定义的更加灵活(在描述切入点的方法注解中直接指定key)
		//FAQ?如何获取切入点方法上的注解中的key?(首先获取目标方法,然后基于目标方法获取方法上注解,再通过注解取key的值)
		String KEY="";
		Class<?> class1 = jp.getTarget().getClass();
		Method[] method = class1.getMethods();
		for (Method m2 : method) {
			boolean falg = m2.isAnnotationPresent(requestCache.class);
			if(falg) {
			requestCache annotation = m2.getAnnotation(requestCache.class);
			KEY = annotation.key();
			}
		}
		
		Object result = map.get(KEY);
		if(result!=null) return result;
		//2.假如cache中没有再去查询目标方法
		result = jp.proceed();
		//3.获取数据后将数据保存在cache中
		System.out.println("put cache");
		map.put(KEY, result);
		return result;
	}
}
